package Test;

import static org.junit.Assert.*;

import java.util.LinkedList;
import java.util.Stack;

import org.junit.Test;

import borderPatrol.Data.Board;
import borderPatrol.Data.Move;
import borderPatrol.Data.SimulationBoard;
import borderPatrol.misc.Cloner;
import borderPatrol.misc.History;

public class SimulationBoardTest {

	@Test
	public void makeSingleMoveTestForPoacher() {

		SimulationBoard board = new SimulationBoard(3, 3);

		board.makeSingleMove(new Move(0, 0), 1);

		assertEquals(0, board.getPoacherPosition()[0]);
		assertEquals(0, board.getPoacherPosition()[1]);
		assertEquals(-1, board.getPatrollerPosition()[0]);
		assertEquals(-1, board.getPatrollerPosition()[1]);
		assertEquals(1, board.getRound());
		assertEquals("1.00", board.getPoacherId());
	}

	@Test
	public void makeSingleMoveTestForPatroller() {

		SimulationBoard board = new SimulationBoard(3, 3);

		board.makeSingleMove(new Move(0, 0), 2);

		assertEquals(0, board.getPatrollerPosition()[0]);
		assertEquals(0, board.getPatrollerPosition()[1]);
		assertEquals(-1, board.getPoacherPosition()[0]);
		assertEquals(-1, board.getPoacherPosition()[1]);
		assertEquals(1, board.getRound());
		assertEquals("2.00", board.getPatrollerId());
	}

	@Test
	public void reverseToPositionTest() {

		SimulationBoard board = new SimulationBoard(3, 3);

		board.makeSingleMove(new Move(0, 0), 2);
		board.makeSingleMove(new Move(0, 1), 2);

		board.reverseToPosition(new int[] { 0, 0 }, new LinkedList<History>(), 2);

		assertEquals(0, board.getPatrollerPosition()[0]);
		assertEquals(0, board.getPatrollerPosition()[1]);
		assertEquals(-1, board.getPoacherPosition()[0]);
		assertEquals(-1, board.getPoacherPosition()[1]);
		assertEquals(1, board.getRound());
		assertEquals("2.00", board.getPatrollerId());
	}

	@Test
	public void possibleHistoriesTest() {

		SimulationBoard board = new SimulationBoard(3, 3);

		board.makeSingleMove(new Move(2, 0), 2);

		assertEquals(2, board.getPatrollerPosition()[0]);
		assertEquals(0, board.getPatrollerPosition()[1]);
		assertEquals(-1, board.getPoacherPosition()[0]);
		assertEquals(-1, board.getPoacherPosition()[1]);
		assertEquals(1, board.getRound());
		assertEquals("2.20", board.getPatrollerId());
		assertEquals(3, board.getPossibleHistoriesForPlayer(1).size());
		
	}
	
	@Test
	public void possibleHistoriesTestOne() {

		SimulationBoard board = new SimulationBoard(3, 3);

		board.makeSingleMove(new Move(2, 0), 2);
		board.makeSingleMove(new Move(2, 1), 2);

		assertEquals(2, board.getPatrollerPosition()[0]);
		assertEquals(1, board.getPatrollerPosition()[1]);
		assertEquals(-1, board.getPoacherPosition()[0]);
		assertEquals(-1, board.getPoacherPosition()[1]);
		assertEquals(2, board.getRound());
		assertEquals("2.20.21", board.getPatrollerId());
		assertEquals(7, board.getPossibleHistoriesForPlayer(1).size());
	}
	
	@Test
	public void possibleHistoriesTestTwo() {

		SimulationBoard board = new SimulationBoard(3, 3);

		board.makeSingleMove(new Move(0, 0), 1);
		board.makeSingleMove(new Move(0, 1), 1);

		assertEquals(-1, board.getPatrollerPosition()[0]);
		assertEquals(-1, board.getPatrollerPosition()[1]);
		assertEquals(0, board.getPoacherPosition()[0]);
		assertEquals(1, board.getPoacherPosition()[1]);
		assertEquals(2, board.getRound());
		assertEquals("1.00.01", board.getPoacherId());
		assertEquals(7, board.getPossibleHistoriesForPlayer(2).size());

	}
	
	@Test
	public void possibleHistoriesTestThree() {

		SimulationBoard board = new SimulationBoard(3, 3);

		board.makeSingleMove(new Move(2, 0), 2);
		board.makeSingleMove(new Move(2, 1), 2);
		board.makeSingleMove(new Move(2, 0), 2);

		assertEquals(2, board.getPatrollerPosition()[0]);
		assertEquals(0, board.getPatrollerPosition()[1]);
		assertEquals(-1, board.getPoacherPosition()[0]);
		assertEquals(-1, board.getPoacherPosition()[1]);
		assertEquals(3, board.getRound());
		assertEquals("2.20.21.20", board.getPatrollerId());
		assertEquals(17, board.getPossibleHistoriesForPlayer(1).size());

	}
	
	@Test
	public void possibleHistoriesTestFour() {

		SimulationBoard board = new SimulationBoard(3, 3);

		board.makeSingleMove(new Move(2, 0), 2);
		board.makeSingleMove(new Move(2, 1), 2);
		board.makeSingleMove(new Move(2, 0), 2);
		board.makeSingleMove(new Move(2, 1), 2);

		assertEquals(2, board.getPatrollerPosition()[0]);
		assertEquals(1, board.getPatrollerPosition()[1]);
		assertEquals(-1, board.getPoacherPosition()[0]);
		assertEquals(-1, board.getPoacherPosition()[1]);
		assertEquals(4, board.getRound());
		assertEquals("2.20.21.20.21", board.getPatrollerId());
		assertEquals(39, board.getPossibleHistoriesForPlayer(1).size());
		
	}
	
	@Test
	public void possibleHistoriesTestFive() {

		SimulationBoard board = new SimulationBoard(3, 3);

		board.makeSingleMove(new Move(2, 0), 2);
		board.makeSingleMove(new Move(2, 1), 2);
		board.makeSingleMove(new Move(2, 0), 2);
		board.makeSingleMove(new Move(2, 1), 2);
		board.makeSingleMove(new Move(2, 0), 2);

		assertEquals(2, board.getPatrollerPosition()[0]);
		assertEquals(0, board.getPatrollerPosition()[1]);
		assertEquals(-1, board.getPoacherPosition()[0]);
		assertEquals(-1, board.getPoacherPosition()[1]);
		assertEquals(5, board.getRound());
		assertEquals("2.20.21.20.21.20", board.getPatrollerId());
		assertEquals(72, board.getPossibleHistoriesForPlayer(1).size());

	}
	
	@Test
	public void possibleHistoriesTestWithReverseMove() {;

		SimulationBoard board = new SimulationBoard(3, 3);

		board.makeSingleMove(new Move(2, 0), 2);
		board.makeSingleMove(new Move(2, 1), 2);
		board.makeSingleMove(new Move(2, 0), 2);
		board.makeSingleMove(new Move(2, 1), 2);
		
		LinkedList<History> histories = Cloner.cloneHistories(board.getPossibleHistoriesForPlayer(1));
		
		board.makeSingleMove(new Move(2, 0), 2);
		
		board.reverseToPosition(new int[]{2, 1}, histories, 2);

		assertEquals(2, board.getPatrollerPosition()[0]);
		assertEquals(1, board.getPatrollerPosition()[1]);
		assertEquals(-1, board.getPoacherPosition()[0]);
		assertEquals(-1, board.getPoacherPosition()[1]);
		assertEquals(4, board.getRound());
		assertEquals("2.20.21.20.21", board.getPatrollerId());
		assertEquals(39, board.getPossibleHistoriesForPlayer(1).size());
		
	}
	
	@Test
	public void possibleHistoriesTestForPoacherAfterTwoMoves() {

		SimulationBoard board = new SimulationBoard(3, 3);

		board.makeSingleMove(new Move(0, 0), 1);
		board.makeSingleMove(new Move(0, 1), 1);


		assertEquals(-1, board.getPatrollerPosition()[0]);
		assertEquals(-1, board.getPatrollerPosition()[1]);
		assertEquals(0, board.getPoacherPosition()[0]);
		assertEquals(1, board.getPoacherPosition()[1]);
		assertEquals(2, board.getRound());
		assertEquals("1.00.01", board.getPoacherId());
		assertEquals(7, board.getPossibleHistoriesForPlayer(2).size());
	}
	
	@Test
	public void possibleHistoriesTestForPoacherAfterFiveMoves() {

		SimulationBoard board = new SimulationBoard(3, 3);

		board.makeSingleMove(new Move(0, 0), 1);
		board.makeSingleMove(new Move(0, 1), 1);
		board.makeSingleMove(new Move(0, 0), 1);
		board.makeSingleMove(new Move(0, 1), 1);
		board.makeSingleMove(new Move(0, 0), 1);

		assertEquals(-1, board.getPatrollerPosition()[0]);
		assertEquals(-1, board.getPatrollerPosition()[1]);
		assertEquals(0, board.getPoacherPosition()[0]);
		assertEquals(0, board.getPoacherPosition()[1]);
		assertEquals(5, board.getRound());
		assertEquals("1.00.01.00.01.00", board.getPoacherId());
		assertEquals(137, board.getPossibleHistoriesForPlayer(2).size());
		
	}
	
//	@Test
//	public void possibleHistoriesTestForPoacherAfterSevenMoves() {
//
//		SimulationBoard board = new SimulationBoard(3, 3);
//
//		board.makeSingleMove(new Move(0, 1), 1);
//		board.makeSingleMove(new Move(0, 0), 1);
//		board.makeSingleMove(new Move(0, 1), 1);
//		board.makeSingleMove(new Move(0, 0), 1);
//		board.makeSingleMove(new Move(0, 1), 1);
//		board.makeSingleMove(new Move(0, 0), 1);
//		board.makeSingleMove(new Move(0, 1), 1);
//
//		assertEquals(-1, board.getPatrollerPosition()[0]);
//		assertEquals(-1, board.getPatrollerPosition()[1]);
//		assertEquals(0, board.getPoacherPosition()[0]);
//		assertEquals(1, board.getPoacherPosition()[1]);
//		assertEquals(7, board.getRound());
//		assertEquals("1.01.00.01.00.01.00.01", board.getPoacherId());
//		assertEquals(1010, board.getPossibleHistoriesForPlayer(2).size());
//		
//	}
//	
//	@Test
//	public void possibleHistoriesTestForPoacherAfterSevenMovesWithOpponentsPosition() {
//
//		SimulationBoard board = new SimulationBoard(3, 3);
//
//		board.makeMove(new Move(0, 1), 1);
//		board.makeMove(new Move(2, 1), 2);
//		
//		board.endTurn();
//		
//		board.resetOpponentPosition(1);
//		
//		board.makeSingleMove(new Move(0, 0), 1);
//		board.makeSingleMove(new Move(0, 1), 1);
//		board.makeSingleMove(new Move(0, 0), 1);
//		board.makeSingleMove(new Move(0, 1), 1);
//		board.makeSingleMove(new Move(0, 0), 1);
//		board.makeSingleMove(new Move(0, 1), 1);
//
//		assertEquals(-1, board.getPatrollerPosition()[0]);
//		assertEquals(-1, board.getPatrollerPosition()[1]);
//		assertEquals(0, board.getPoacherPosition()[0]);
//		assertEquals(1, board.getPoacherPosition()[1]);
//		assertEquals(7, board.getRound());
//		assertEquals("1.01.00.01.00.01.00.01", board.getPoacherId());
//		assertEquals(1010, board.getPossibleHistoriesForPlayer(2).size());
//		
////		System.out.println(board.getPossibleHistoriesForPlayer(2));
//		
//	}
	
	@Test
	public void isTerminalWithExternalHistoryTest() {

		SimulationBoard board = new SimulationBoard(3, 3);
		
		board.makeSingleMove(new Move(0, 0), 1);
		board.makeSingleMove(new Move(1, 0), 1);
		board.makeSingleMove(new Move(2, 0), 1);
		
		Stack<int[]> sequence = new Stack<int[]>();
		
		sequence.push(new int[]{-1, -1});
		sequence.push(new int[]{2, 1});
		sequence.push(new int[]{2, 0});
		sequence.push(new int[]{1, 0});
		
		assertEquals(2, board.isTerminal(sequence, 1));
		
	}
	
	@Test
	public void isTerminalWithExternalHistoryTestOne() {

		Board board = new SimulationBoard(3, 3);
		
		board.makeMove(new Move(0, 1), 1);
		board.makeMove(new Move(2, 0), 2);
		
		board.endTurn();
		
		board.makeMove(new Move(0, 0), 1);
		board.makeMove(new Move(2, 1), 2);
		
		board.endTurn();
		
		board.makeMove(new Move(1, 0), 1);
		board.makeMove(new Move(2, 0), 2);
		
		board.endTurn();
		
		SimulationBoard newboard = board.getSimulationBoard();
		
		Stack<int[]> sequence = new Stack<int[]>();
		
		sequence.push(new int[]{-1, -1});
		sequence.push(new int[]{2, 0});
		sequence.push(new int[]{1, 0});
		sequence.push(new int[]{0, 0});
		
		assertEquals(2, newboard.isTerminal(sequence, 1));
		
	}

}
